在上下滑动通知栏过程中,伴随着 QSTile 联动的一些动画,这些动画是由 QSAnimator 实现的。
在QS做扩展或者收缩动画时,会调用 QSAnimator 的 setPosition()
方法来更新所有 View 的属性来实现相应动画效果。
1 | NotificationPanelViewController.setQsExpansion() |
另外,QSAnimator 实现了 OnLayoutChangeListener 接口,并且在初始化时为 QSContainerImpl 添加了监听器。
1 | qs.getView().addOnLayoutChangeListener(this) |
在 QSFragment 中有个 QSAnimator 对象,它会在 updateAnimators() 方法中构建所有的 TouchAnimator.Builder()
对象,并且绑定需要做动画的属性。当QS布局变化时,会调用 QSAnimator 的 setPosition()
方法来更新所有 View 的属性来实现相应动画效果。
1 | QSAnimator.onLayoutChange() |
TouchAnimator是对动画类的封装,而其内建的Builder是对动画参数的配置,build方法直接返回了一个 TouchAnimator 对象。
下面我们以亮度条的缩放为例来介绍一下。
1 | // QSAnimator.java |
updateAnimators() 方法中构造了 TouchAnimator 对象,设置了需要做动画的属性。
1 | //TouchAnimator.java |
FloatKeyframeSet 继承自 KeyframeSet,可以为View的一些属性设置float类型的值。它保存了我们为动画设置的View属性的名称、关键帧的个数、以及属性的数值。
比如 addFloat(brightness, "alpha", 0, 1)
我们就为 brightness 进行 alpha 属性的变化,关键帧的个数为2个,只设置了初始值和目标值,分别为 0 和 1 。后面就会根据QS的位置以及view的alpha的初始值和目标值计算出当前应该为brightness设置的alpha的值。通过这样来实现根据QS位置的变化来达到brightness透明度变化以及SCALE_Y变化的目的。
再来看看动画的执行:
1 | QSAnimator.setPosition() |
1 | //TouchAnimator.java |
关键的mProperty.set语句实际上就相当于:View.SCALE_Y.setValue(view, scale) -> BrightnessSliderView.setScaleY(scale),为View的某个属性设置一个数值。